#!/usr/bin/env bash

set -e

# ----------- 请根据实际情况，修改如下配置 ------------ #

#是否安装测试数据(on:是，off:否)
SITE_DEMO=off

#站点域名(不包括http)
SITE_DOMAIN=abc.com

# ------------ @@@ 以下内容，非专业人士请勿修改，新手请远离！ @@@ ------------- #

#普通信息输出
normal_print() {
  echo -e "\033[34m \n $1 \n \033[0m"
}

#成功信息输出
success_print() {
  echo -e "\033[32m \n $1 \n \033[0m"
}

#失败信息输出
error_print() {
  echo -e "\033[31m \n $1 \n \033[0m"
}

#生成随机字符串
random_str() {
  local length=$1
  if [ -z "$length" ]; then
    length=16
  fi
  tr -dc 'a-zA-Z0-9' </dev/urandom | fold -w "$length" | head -n 1
}

#判断镜像存在
image_exists() {
  local image=$1
  if docker image inspect "$image" >/dev/null 2>&1; then
    echo 'yes'
  else
    echo 'no'
  fi
}

#系统判断
os_type() {
  if [ ! -f /etc/os-release ]; then
    echo "other"
    return 1
  fi

  # 获取ID和ID_LIKE（去除引号）
  local os_id os_like
  os_id=$(grep '^ID=' /etc/os-release | cut -d= -f2 | tr -d '"')
  os_like=$(grep '^ID_LIKE=' /etc/os-release | cut -d= -f2 | tr -d '"')

  # 主判断逻辑
  if [[ "$os_id" == "centos" || "$os_id" == "rhel" || "$os_id" == "almalinux" || "$os_id" == "rocky" || "$os_id" == "ol" ]]; then
    echo "rhel" # 统一返回RHEL兼容系
  elif [[ "$os_id" == "ubuntu" ]]; then
    echo "ubuntu"
  elif [[ "$os_id" == "debian" ]]; then
    echo "debian"
  elif [[ "$os_id" == "opensuse-leap" || "$os_id" == "sles" ]]; then
    echo "suse"
  else
    # 处理衍生版（通过ID_LIKE判断）
    if [[ "$os_like" == *"rhel"* || "$os_like" == *"centos"* || "$os_like" == *"fedora"* ]]; then
      echo "rhel"
    elif [[ "$os_like" == *"suse"* ]]; then
      echo "suse"
    elif [[ "$os_like" == *"debian"* ]]; then
      echo "debian"
    else
      echo "other"
    fi
  fi
}

#mysql超级用户密码（数字字母组合，不要用特殊字符）
MYSQL_ROOT_PASSWORD=$(random_str 16)

#mysql主机名称（非独立实例请不要修改，独立实例填写主机IP）
MYSQL_HOST=mysql

#mysql主机端口（非独立实例请不要修改）
MYSQL_PORT=3306

#mysql项目数据库名称（数字字母组合，不要用特殊字符）
MYSQL_DATABASE=ctc

#mysql项目数据库用户（数字字母组合，不要用特殊字符）
MYSQL_USER=ctc

#mysql项目数据库密码（数字字母组合，不要用特殊字符）
MYSQL_PASSWORD=$(random_str 16)

#redis主机名称（非独立实例请不要修改，独立实例填写主机IP）
REDIS_HOST=redis

#redis访问密码（数字字母组合，不要用特殊字符）
REDIS_PASSWORD=$(random_str 16)

#基准目录
base_dir=~/ctc-docker

#ctc目录
ctc_dir=${base_dir}/html/ctc

#解析参数
while [[ $# -gt 0 ]]; do
  case "$1" in
  --demo)
    SITE_DEMO="$2"
    shift 2
    ;;
  --domain)
    SITE_DOMAIN="$2"
    shift 2
    ;;
  *)
    echo "unknown param: $1" >&2
    exit 1
    ;;
  esac
done

#判断root用户
if [[ $EUID -ne 0 ]]; then
  error_print "------ this script must be run as root ------"
  exit 1
fi

#判断系统架构
if [[ "$(uname -m)" != "x86_64" ]]; then
    error_print "------ we only support x86_64 architecture currently ------"
    exit 1
fi

normal_print "------ update host system ------"

os=$(os_type) || {
  error_print "failed to detect OS type"
  exit 1
}

#安装git和curl
if [ "${os}" = 'ubuntu' ] || [ "${os}" = 'debian' ]; then
  apt-get update
  apt-get install -y curl git
elif [ "${os}" = 'rhel' ]; then
  if [ -z "$(command -v dnf)" ]; then
    yum update
    yum install -y curl git
  else
    dnf update
    dnf install -y curl git
  fi
elif [ "${os}" = 'suse' ]; then
  zypper refresh
  zypper install -y curl git
else
  error_print "unsupported OS: ${os} (we only support ubuntu|debian|rhel|suse)"
  exit 1
fi

normal_print "------ git clone ctc-docker ------"

#克隆ctc-docker项目
if [ ! -d ${base_dir} ]; then
  git clone --depth 1 https://gitee.com/koogua/course-tencent-cloud-docker.git ${base_dir}
else
  cd ${base_dir} && git pull --no-rebase
fi

normal_print "------ git clone ctc ------"

#克隆ctc项目
if [ ! -d ${ctc_dir} ]; then

  git clone --depth 1 https://gitee.com/koogua/course-tencent-cloud.git ${ctc_dir}

  #忽略文件模式（权限）变更
  git config --global core.fileMode false

  #加入安全目录
  git config --global --add safe.directory ${ctc_dir}

else
  cd ${ctc_dir} && git pull --no-rebase
fi

#docker .env文件
docker_env=${base_dir}/.env

#复制环境变量文件
cp ${base_dir}/.env.default ${docker_env}

#替换docker .env配置项
sed -i "s/MYSQL_ROOT_PASSWORD.*/MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}/g" ${docker_env}
sed -i "s/MYSQL_DATABASE.*/MYSQL_DATABASE=${MYSQL_DATABASE}/g" ${docker_env}
sed -i "s/MYSQL_USER.*/MYSQL_USER=${MYSQL_USER}/g" ${docker_env}
sed -i "s/MYSQL_PASSWORD.*/MYSQL_PASSWORD=${MYSQL_PASSWORD}/g" ${docker_env}
sed -i "s/REDIS_PASSWORD.*/REDIS_PASSWORD=${REDIS_PASSWORD}/g" ${docker_env}

#nginx配置目录
nginx_conf_dir=${base_dir}/nginx/conf.d
nginx_default_conf=${nginx_conf_dir}/default.conf

#复制nginx站点配置文件
cp ${nginx_conf_dir}/default.conf.sample ${nginx_default_conf}

#替换nginx default.conf配置项
sed -i "s/server_name .*/server_name ${SITE_DOMAIN};/g" ${nginx_default_conf}

#ctc config目录
ctc_config_dir=${ctc_dir}/config
ctc_config_php=${ctc_config_dir}/config.php

#复制config.php
cp ${ctc_config_dir}/config.default.php ${ctc_config_php}

#生成随机站点密钥
site_key=$(random_str 16)

#替换config.php配置项
sed -i "s/\$config\['key'\].*/\$config['key'] = '${site_key}';/g" ${ctc_config_php}
sed -i "s/\$config\['db'\]\['host'\].*/\$config['db']['host'] = '${MYSQL_HOST}';/g" ${ctc_config_php}
sed -i "s/\$config\['db'\]\['port'\].*/\$config['db']['port'] = '${MYSQL_PORT}';/g" ${ctc_config_php}
sed -i "s/\$config\['db'\]\['dbname'\].*/\$config['db']['dbname'] = '${MYSQL_DATABASE}';/g" ${ctc_config_php}
sed -i "s/\$config\['db'\]\['username'\].*/\$config['db']['username'] = '${MYSQL_USER}';/g" ${ctc_config_php}
sed -i "s/\$config\['db'\]\['password'\].*/\$config['db']['password'] = '${MYSQL_PASSWORD}';/g" ${ctc_config_php}
sed -i "s/\$config\['redis'\]\['host'\].*/\$config['redis']['host'] = '${REDIS_HOST}';/g" ${ctc_config_php}
sed -i "s/\$config\['redis'\]\['auth'\].*/\$config['redis']['auth'] = '${REDIS_PASSWORD}';/g" ${ctc_config_php}
sed -i "s/\$config\['websocket'\]\['connect_address'\].*/\$config['websocket']['connect_address'] = '${SITE_DOMAIN}:8282';/g" ${ctc_config_php}

#复制xunsearch配置文件
cp ${ctc_config_dir}/xs.course.default.ini ${ctc_config_dir}/xs.course.ini
cp ${ctc_config_dir}/xs.article.default.ini ${ctc_config_dir}/xs.article.ini
cp ${ctc_config_dir}/xs.question.default.ini ${ctc_config_dir}/xs.question.ini

normal_print "------ install docker ------"

#安装docker
if [ -z "$(command -v docker)" ]; then
  bash ${base_dir}/get-docker.sh --mirror Aliyun
fi

if [ -z "$(command -v docker)" ]; then
  error_print "------ docker command not found, please try again ------"
  exit 1
fi

if [ ! -d '/etc/docker' ]; then
  mkdir -p '/etc/docker'
fi

#docker镜像加速
if [ ! -e '/etc/docker/daemon.json' ]; then
  tee -a /etc/docker/daemon.json <<-EOF
{
  "registry-mirrors": [
    "https://mirror.ccs.tencentyun.com"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "500m",
    "max-file": "3"
  }
}
EOF
  systemctl daemon-reload
  systemctl restart docker
  chmod 666 /var/run/docker.sock
fi

normal_print "------ install docker-compose ------"

docker_compose_url="https://download.koogua.com/docker-compose-linux-x86_64"

#安装docker-compose
if [ -z "$(command -v docker-compose)" ]; then
  curl --retry 3 --retry-delay 5 --retry-max-time 30 "${docker_compose_url}" -o /usr/local/bin/docker-compose
  chmod +x /usr/local/bin/docker-compose
fi

if [ -z "$(command -v docker-compose)" ]; then
  error_print "------ docker-compose command not found, please try again ------"
  exit 1
fi

#设置ctc目录属主
chown -R 33:33 ${ctc_dir}

#mysql日志目录
mysql_log_dir=${base_dir}/mysql/log

#修改mysql日志目录的属主，否则启动不了
chown -R 999:999 ${mysql_log_dir}

#切换到基准目录
cd ${base_dir} || exit

normal_print "------ fetch & load docker images ------"

download_dir=https://download.koogua.com/docker-images

if [ "$(image_exists nginx:1.18)" = 'no' ]; then
  file=nginx-1.18.tar.gz
  curl --retry 3 --retry-delay 5 --retry-max-time 30 -O ${download_dir}/${file}
  docker load -i ${file}
  rm -f ${file}
fi

if [ "$(image_exists mysql:5.7)" = 'no' ]; then
  file=mysql-5.7.tar.gz
  curl --retry 3 --retry-delay 5 --retry-max-time 30 -O ${download_dir}/${file}
  docker load -i ${file}
  rm -f ${file}
fi

if [ "$(image_exists redis:5.0)" = 'no' ]; then
  file=redis-5.0.tar.gz
  curl --retry 3 --retry-delay 5 --retry-max-time 30 -O ${download_dir}/${file}
  docker load -i ${file}
  rm -f ${file}
fi

if [ "$(image_exists hightman/xunsearch:latest)" = 'no' ]; then
  file=hightman-xunsearch-latest.tar.gz
  curl --retry 3 --retry-delay 5 --retry-max-time 30 -O ${download_dir}/${file}
  docker load -i ${file}
  rm -f ${file}
fi

if [ "$(image_exists xiaochong0302/php:ctc)" = 'no' ]; then
  file=xiaochong0302-php-ctc.tar.gz
  curl --retry 3 --retry-delay 5 --retry-max-time 30 -O ${download_dir}/${file}
  docker load -i ${file}
  rm -f ${file}
fi

normal_print "------ build docker images ------"

docker-compose up -d

#等待mysql服务
docker exec -i ctc-php bash <<'EOF'

until nc -z -v -w30 mysql 3306 &> /dev/null
do
  echo "waiting for mysql service..."
  sleep 2
done

exit
EOF

#导入测试数据
if [ "${SITE_DEMO}" = 'on' ]; then

  demo_sql=${base_dir}/mysql/data/demo.sql.gz

  normal_print "------ import demo.sql.gz ------"

  curl --retry 3 --retry-delay 5 --retry-max-time 30 https://download.koogua.com/ctc/demo.sql.gz -o ${demo_sql}

  docker exec -i ctc-mysql bash <<'EOF'

    gunzip < /var/lib/mysql/demo.sql.gz | mysql -u ${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_DATABASE}

  exit

EOF

  rm -f ${demo_sql}

fi

normal_print "------ ctc upgrade ------"

#使用www-data用户运行，避免权限问题
docker exec -i --user www-data:www-data ctc-php bash <<'EOF'

ctc_dir=/var/www/html/ctc

#切换到ctc目录
cd ${ctc_dir}

echo -e "\n------ install composer packages ------\n"

#安装依赖包
composer install --no-dev
composer dump-autoload --optimize

echo -e "\n------ phinx migrate ------\n"

#数据迁移
vendor/bin/phinx migrate

echo -e "\n------ php console upgrade ------\n"

#程序升级
php console.php upgrade

echo -e "\n------ rebuild xunsearch index ------\n"

#重建xunsearch索引
php console.php course_index rebuild
php console.php article_index rebuild
php console.php question_index rebuild

#清理log
rm -f storage/log/*.log

exit
EOF

#重启php容器（websocket依赖WorkerGateway相关包，之前启动php容器时并未安装相关包）
docker container restart ctc-php

docker_ps=$(docker ps)

if [[ "${docker_ps}" =~ 'nginx' ]]; then
  success_print "------ nginx service ok ------"
else
  error_print "------ nginx service failed ------"
fi

if [[ "${docker_ps}" =~ 'php' ]]; then
  success_print "------ php service ok ------"
else
  error_print "------ php service failed ------"
fi

if [[ "${docker_ps}" =~ 'mysql' ]]; then
  success_print "------ mysql service ok ------"
else
  error_print "------ mysql service failed ------"
fi

if [[ "${docker_ps}" =~ 'redis' ]]; then
  success_print "------ redis service ok ------"
else
  error_print "------ redis service failed ------"
fi

if [[ "${docker_ps}" =~ 'xunsearch' ]]; then
  success_print "------ xunsearch service ok ------"
else
  error_print "------ xunsearch service failed ------"
fi
